﻿using System;
using System.Data.Services.Client;
using System.Linq;
using BusinessObjects;
using YourWorld.Common.GreenWorldEntitiesService;
using YourWorld.Common.Infrastucture.Events;
using System.Collections.Generic;
using MainGameModule.Models;
using System.Windows;

namespace LogInModule.Models
{
    public class LoginModel : ILoginModel
    {
        public event Action<DataServiceCollection<User>> UsersLoaded;
        public event Action<Player> LoginSuccessful;
        public event Action<Exception> LoginFailed;
        public event Action WrongCredentialsEvent;

        private const string ServiceUrl = @"http://48de1d712dd7438f8e308ea3b1e69aae.cloudapp.net/GreenWorldDataService.svc";
        private GreenWorldEntities context;

        private DataServiceCollection<User> trackedUsers = null;

        public LoginModel()
        {
            this.context = new GreenWorldEntities( new Uri( ServiceUrl, UriKind.RelativeOrAbsolute ) );
        }

        public void Login( Player player )
        {
            EventService.Aggregator.GetEvent<PlayerLoginSuccessfulEvent>().Publish( player );
        }

        public void LoadUser( string email, string password )
        {
            var userQuery = ( from r in this.context.Users
                              where r.Email == email && r.Password == password
                              select r ) as DataServiceQuery<User>;

            userQuery.BeginExecute( new AsyncCallback( this.LoadUserCompleted ), userQuery );

        }

        public void AddUser(string email, string password)
        {
            var userQuery = (from r in this.context.Users
                             where r.Email == email && r.Password == password
                             select r) as DataServiceQuery<User>;

            userQuery.BeginExecute(new AsyncCallback(this.AddUserCompleted), userQuery);

        }

        public void AddUser(string email, string username, string password)
        {
            User newUser = new User();
            newUser.Email = email;
            newUser.Name = username;
            newUser.Password = password;

            this.context.AddToUsers(newUser);
            
            this.context.BeginSaveChanges(SaveChangesOptions.Batch,
                       (result) =>
                       {
                           PlayersRepository.Instance.Reload();
                           this.AddUser(email, password);
                       },
                       null);
        }

        private void AddUserCompleted(IAsyncResult state)
        {
            var userQueryObject = state.AsyncState as DataServiceQuery<User>;
            List<User> ros = userQueryObject.EndExecute(state).ToList();

            if (ros.Count == 0)
            {
                if (this.WrongCredentialsEvent != null)
                    this.WrongCredentialsEvent();

                return;
            }

            User user = ros[0];
            Player logInPlayer = new Player()
            {
                UserId = user.Id,
                Image = user.PicUrl,
                Name = user.Name,
                Badges = user.Badges,
                Quests = user.Quests,
                Experience = this.GetExperience(user.Experience),
                Level = this.GetLevel(user.GameLevel),
                IsMainPlayer = true
            };

            //PlayersRepository.Instance.Players.Add(logInPlayer);
            //PlayersRepository.Instance.Users.Add(user);

            if (this.LoginSuccessful != null)
                this.LoginSuccessful(logInPlayer);
        }

        private void LoadUserCompleted( IAsyncResult state )
        {
            var userQueryObject = state.AsyncState as DataServiceQuery<User>;
            List<User> ros = userQueryObject.EndExecute( state ).ToList();

            if ( ros.Count == 0 )
            {
                if ( this.WrongCredentialsEvent != null )
                    this.WrongCredentialsEvent();

                return;
            }

            User user = ros[0];
            Player logInPlayer = new Player()
            {
                UserId = user.Id,
                Image = user.PicUrl,
                Name = user.Name,
                Badges = user.Badges,
                Quests = user.Quests,
                Experience = this.GetExperience(user.Experience),
                Level = this.GetLevel(user.GameLevel),
                IsMainPlayer = true
            };

            Deployment.Current.Dispatcher.BeginInvoke( () =>
                {
                    if ( this.LoginSuccessful != null )
                        this.LoginSuccessful( logInPlayer );
                } );
        }

        private int GetExperience(int? experience)
        {
            if (!experience.HasValue)
            {
                return 0;
            }
            else
            {
                return experience.Value;
            }
        }

        private int GetLevel(int? level)
        {
            if (!level.HasValue)
            {
                return 0;
            }
            else
            {
                return level.Value;
            }
        }

        public void GetUsersAsync()
        {
            //var query = from u in this.context.Users
            //            select new YourWorld.Common.GreenWorldEntitiesService.User
            //            {
            //                Color = u.Color,
            //                Email = u.Email,
            //                Experience = u.Experience,
            //                GameLevel = u.GameLevel,
            //                Id = u.Id,
            //                Name = u.Name,
            //                Password = u.Password,
            //                PicUrl = u.PicUrl,
            //                Badges = u.Badges,
            //                Quests = u.Quests
            //            };

            //this.trackedUsers = new DataServiceCollection<YourWorld.Common.GreenWorldEntitiesService.User>();
            //this.trackedUsers.LoadCompleted += new EventHandler<LoadCompletedEventArgs>( OnUsersLoaded );
            //this.trackedUsers.LoadAsync( query );
        }

        public void GetUsersAsync( Action<DataServiceCollection<User>> callback )
        {
            //var query = from u in this.context.Users
            //            select new YourWorld.Common.GreenWorldEntitiesService.User
            //            {
            //                Color = u.Color,
            //                Email = u.Email,
            //                Experience = u.Experience,
            //                GameLevel = u.GameLevel,
            //                Id = u.Id,
            //                Name = u.Name,
            //                Password = u.Password,
            //                PicUrl = u.PicUrl,
            //                Badges = u.Badges,
            //                Quests = u.Quests
            //            };

            //this.trackedUsers = new DataServiceCollection<YourWorld.Common.GreenWorldEntitiesService.User>();
            //this.trackedUsers.LoadCompleted += new EventHandler<LoadCompletedEventArgs>( ( s, e ) => { callback( this.trackedUsers ); } );
            //this.trackedUsers.LoadAsync( query );
        }

        public void SaveUsers( Player newPlayer, AsyncCallback callback )
        {
            this.context.BeginSaveChanges( SaveChangesOptions.Batch,
                ( result ) =>
                {
                    if ( callback != null )
                    {
                        callback( null );
                    }
                },
                null );
        }

        //private void OnUsersLoaded( object sender, LoadCompletedEventArgs e )
        //{
        //    if ( this.UsersLoaded != null )
        //    {
        //        this.UsersLoaded( this.trackedUsers );
        //    }
        //}
    }
}
